/*
 *                        _oo0oo_
 *                       o8888888o
 *                       88" . "88
 *                       (| -_- |)
 *                       0\  =  /0
 *                     ___/`---'\___
 *                   .' \\|     |// '.
 *                  / \\|||  :  |||// \
 *                 / _||||| -:- |||||- \
 *                |   | \\\  - /// |   |
 *                | \_|  ''\---/''  |_/ |
 *                \  .-\__  '-'  ___/-. /
 *              ___'. .'  /--.--\  `. .'___
 *           ."" '<  `.___\_<|>_/___.' >' "".
 *          | | :  `- \`.;`\ _ /`;.`/ - ` : | |
 *          \  \ `_.   \_ __\ /__ _/   .-` /  /
 *      =====`-.____`.___ \_____/___.-`___.-'=====
 *                        `=---='
 *
 *
 *      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *            佛祖保佑       永不宕机     永无BUG
 */

package m

import (
	"GameServer/Common/utils"
	"GameServer/Game/cache"
	"GameServer/Game/dbmodule"
	"GameServer/Game/errors"
	"sync"

	"github.com/globalsign/mgo/bson"
	log "github.com/sirupsen/logrus"
)

var UserFriendsTableName string = "userFriends"

type FriendsBaseData struct {
	Uid          string `bson:"uid" json:"uid"`                   // 好友UID
	FriendTyp    int64  `bson:"friendTyp" json:"friendTyp"`       // 好友类型 0-游戏好友 1-FB好友
	ReciveCount  int64  `bson:"reciveCount" json:"reciveCount"`   // 剩余，可领取奖励数量
	ReciveRecord int64  `bson:"reciveRecord" json:"reciveRecord"` // 历史，领取记录
	SendCount    int64  `bson:"sendCount" json:"sendCount"`       // 历史，已经赠送次数
}

type ReqFriendData struct {
	Uid            string `bson:"uid" json:"uid"`                       // 好友UID
	LastRefuseTime int64  `bson:"lastRefuseTime" json:"lastRefuseTime"` // 上次拒绝时间
}

type UserFriends struct {
	BaseM
	Uid               bson.ObjectId               `bson:"_id" json:"_id"`                             // 玩家UID
	LastRestTime      int64                       `bson:"lastRestTime" json:"lastRestTime"`           // 上次重置时间戳
	InviteFriendNum   int64                       `bson:"inviteFriendNum" json:"inviteFriendNum"`     // 邀请FB好友次数
	SendRecord        int64                       `bson:"sendRecord" json:"sendRecord"`               // 历史赠送次数记录
	ReciveRecord      int64                       `bson:"reciveRecord" json:"reciveRecord"`           // 历史领取次数记录
	TotalReciveNum    int64                       `bson:"totalReciveNum" json:"totalReciveNum"`       // 总共待领取奖励数量
	DailyReqFriendNum int64                       `bson:"dailyReqFriendNum" json:"dailyReqFriendNum"` // 当天请求好友数量
	FriendsLst        map[string]*FriendsBaseData `bson:"friendsLst" json:"friendsLst"`               // 好友基础信息列表
	ReqFriendsLst     map[string]*ReqFriendData   `bson:"reqFriendsLst" json:"reqFriendsLst"`         // 请求加好友列表
	ReqBanFriendsLst  map[string]*ReqFriendData   `bson:"reqBanFriendsLst" json:"reqBanFriendsLst"`   // 被拒绝好友列表,保存被对方拒绝的，对方UID

	ShareNum int64 `bson:"shareNum" json:"shareNum"` // 记录分享次数
	rw       *sync.RWMutex
}

func NewUserFriendsData() cache.EntryI {
	return &UserFriends{
		LastRestTime:      0,
		InviteFriendNum:   0,
		SendRecord:        0,
		ReciveRecord:      0,
		TotalReciveNum:    0,
		DailyReqFriendNum: 0,
		FriendsLst:        make(map[string]*FriendsBaseData),
		ReqFriendsLst:     make(map[string]*ReqFriendData),
		ReqBanFriendsLst:  make(map[string]*ReqFriendData),
	}
}

func (uF *UserFriends) RWLock() *sync.RWMutex {
	if uF.rw == nil {
		uF.rw = new(sync.RWMutex)
	}
	return uF.rw
}

func (uF *UserFriends) Save() (err error) {
	if uF.FriendsLst == nil || len(uF.FriendsLst) == 0 {
		mdata := make(map[string]interface{}, 0)
		mdata["_id"] = uF.Uid
		mdata["lastRestTime"] = uF.LastRestTime
		mdata["inviteFriendNum"] = uF.InviteFriendNum
		mdata["sendRecord"] = uF.SendRecord
		mdata["reciveRecord"] = uF.ReciveRecord
		mdata["totalReciveNum"] = uF.TotalReciveNum
		mdata["dailyReqFriendNum"] = uF.DailyReqFriendNum
		err = dbmodule.MgoDB.GameDB.Upsert(UserFriendsTableName, bson.M{"_id": uF.Uid}, mdata)
		if err != nil {
			return
		}
		return
	}
	err = dbmodule.MgoDB.GameDB.Upsert(UserFriendsTableName, bson.M{"_id": uF.Uid}, uF)
	if err != nil {
		return
	}
	return
}

func (uF *UserFriends) Load(key interface{}) (err error) {
	switch key.(type) {
	case string:
		if key.(string) == "" {
			return errors.New("无效的key load, key empty")
		}
		uF.Uid = bson.ObjectIdHex(key.(string))
	case bson.ObjectId:
		uF.Uid = key.(bson.ObjectId)
	default:
		log.WithFields(log.Fields{
			"method": "ScryerInfoData_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return uF.LoadData()
}

func (uF *UserFriends) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne(UserFriendsTableName, bson.M{"_id": uF.Uid}, nil, &uF)
	if err != nil {
		if err.Error() == "not found" {
			return nil
		}
		return
	}
	if uF.FriendsLst == nil {
		uF.FriendsLst = make(map[string]*FriendsBaseData, 0)
	}
	if uF.ReqFriendsLst == nil {
		uF.ReqFriendsLst = make(map[string]*ReqFriendData, 0)
	}
	if uF.ReqBanFriendsLst == nil {
		uF.ReqBanFriendsLst = make(map[string]*ReqFriendData, 0)
	}
	return
}

func (uF *UserFriends) Update(val *UserFriends) {
	Cache.Put(UserFriendsTableName, uF.Uid.Hex(), val)
	val.UpdateData()
}

// 获取，缓存中，用户的好友系统信息
func (u *User) GetUserFriendsData() (r *UserFriends) {
	v, _ := Cache.Get(UserFriendsTableName, u.Uid.Hex())
	r = v.(*UserFriends)
	if r.FriendsLst == nil {
		r.FriendsLst = make(map[string]*FriendsBaseData, 0)
	}
	if r.ReqFriendsLst == nil {
		r.ReqFriendsLst = make(map[string]*ReqFriendData, 0)
	}
	if r.ReqBanFriendsLst == nil {
		r.ReqBanFriendsLst = make(map[string]*ReqFriendData, 0)
	}
	nowTime := utils.TNow().Unix()
	isSameDay := utils.IsSameDay(r.LastRestTime, nowTime)

	if isSameDay == false {
		r.LastRestTime = nowTime
		// r.InviteFriendNum // 邀请次数不变
		r.SendRecord = 0        // 历史赠送次数
		r.ReciveRecord = 0      // 历史领取数量
		r.TotalReciveNum = 0    // 总领取数量
		r.DailyReqFriendNum = 0 // 当天请求好友数量
		if len(r.FriendsLst) > 0 {
			for _, fData := range r.FriendsLst {
				fData.ReciveCount = 0  // 剩余，可领取数量
				fData.ReciveRecord = 0 // 历史，领取次数
				fData.SendCount = 0    // 历史，已经赠送次数
			}
		}
		r.Update(r)
	}
	return
}

// 添加好友
func (uF *UserFriends) AddFriend(fD *FriendsBaseData) {
	if fD.Uid == uF.Uid.Hex() {
		// 不能自己加自己
		return
	}
	defer uF.Update(uF)
	uF.RWLock().Lock()
	// 写入新好友数据
	uF.FriendsLst[fD.Uid] = &FriendsBaseData{
		Uid:          fD.Uid,
		FriendTyp:    fD.FriendTyp,
		ReciveCount:  fD.ReciveCount,
		ReciveRecord: fD.ReciveRecord,
		SendCount:    fD.SendCount,
	}
	// 新加好友，从自己收到的申请列表中，移除
	delete(uF.ReqFriendsLst, fD.Uid)
	// 新加好友，看看在不在自己的被拒绝列表中
	delete(uF.ReqBanFriendsLst, fD.Uid)
	// 刷新玩家数据
	uF.RWLock().Unlock()
	return
}

// 删除好友
func (uF *UserFriends) DeleteFriend(uid string) {
	defer uF.Update(uF)
	uF.RWLock().Lock()
	theData, ok := uF.FriendsLst[uid]
	if ok {
		// 检查是否有未领取的奖励，清空
		if theData.ReciveCount > 0 {
			uF.TotalReciveNum = uF.TotalReciveNum - theData.ReciveCount
			if uF.TotalReciveNum <= 0 {
				uF.TotalReciveNum = 0
			}
		}
		// 删除
		delete(uF.FriendsLst, uid)
	}
	uF.RWLock().Unlock()
	return
}

// 邀请好友成功
func (uF *UserFriends) AddInviteFriendNum(addNum int64) {
	defer uF.Update(uF)
	uF.RWLock().Lock()
	uF.InviteFriendNum = uF.InviteFriendNum + addNum
	uF.RWLock().Unlock()
	return
}

// 添加到申请列表
func (uF *UserFriends) AddReqFriendLst(uid string) {
	if uid == uF.Uid.Hex() {
		// 不能自己加自己
		return
	}
	defer uF.Update(uF)
	uF.RWLock().Lock()
	// 写入新好友数据
	uF.ReqFriendsLst[uid] = &ReqFriendData{
		Uid:            uid,
		LastRefuseTime: 0,
	}
	// 刷新玩家数据
	uF.RWLock().Unlock()
	return
}

// 从申请列表中移除
func (uF *UserFriends) RemoveReqFriendLst(uid string) {
	defer uF.Update(uF)
	uF.RWLock().Lock()
	// 写入新好友数据
	delete(uF.ReqFriendsLst, uid)
	// 刷新玩家数据
	uF.RWLock().Unlock()
	return
}

// 添加到被拒绝列表
func (uF *UserFriends) AddInBanLst(uid string, refuseTime int64) {
	defer uF.Update(uF)
	uF.RWLock().Lock()
	// 写入被拒绝数据
	uF.ReqBanFriendsLst[uid] = &ReqFriendData{
		Uid:            uid,
		LastRefuseTime: refuseTime,
	}
	// 刷新玩家数据
	uF.RWLock().Unlock()
	return
}

// 从被拒绝列表中移除
func (uF *UserFriends) RemoveInBanLst(uid string) {
	defer uF.Update(uF)
	uF.RWLock().Lock()
	// 写入被拒绝数据
	delete(uF.ReqBanFriendsLst, uid)
	// 刷新玩家数据
	uF.RWLock().Unlock()
	return
}
